package MuleBackend;

import java.util.ArrayList;
import java.util.Random;

/**
 * holds all the lands and represents the Map on which MULE takes place
 * @author Andrew
 *
 */
public class Board {
	Land[][] lands;
	//nextFreeLand is used to hold the freeLand from the land Sale phase so that it can be used in the Land Auction phase
	Land nextFreeLand;
	ArrayList<Integer>crystiteR,crystiteC;
	/**
	 * constructor for the board
	 * holds a 2d array of all the lands
	 */
	public Board(){
		lands = new Land[5][9];
		crystiteR=new ArrayList<Integer>();
		crystiteC=new ArrayList<Integer>();
	}

	/**
	 *  @return the string representation of the board
	 */
	/*public String toString(){
		String string = "";
		for (Land land : getLands()) {
			string += land.toString();
		}
		return string;
	}*/
	
	/**
	 * generates the board based on the map selected
	 * @param num the map selected
	 */
	public void createMap(int num){
		LandFactory factory = new LandFactory();
		String layout = mapPattern(num);
		int index = 0;
		for (int i = 0; i < lands.length;i++){
			for (int j = 0; j < lands[i].length; j++){
				lands[i][j] = factory.createLand(layout.charAt(index)-48);
				lands[i][j].setLocation(i, j);
				index++;
				System.out.println(lands[i][j].toString());
			}
		}
		for(int i=0;i<3;i++){
			addCrystiteDeposit();
		}
	}
	
	/**
	 * adds crystite deposits to the board.
	 */
	public void addCrystiteDeposit(){
		
		//you can't have more than 5 crystite deposits on the board at once
		if(crystiteR.size()>5)return;
		
		int r;
		int c;
		
		//make sure you can't have deposits in the shop or where you already have crystite deposits.
		randomizing:
		do{
			r=(int) (Math.random() * lands.length);
			c=(int) (Math.random() * lands[0].length);
			if(r==3&&c==5)continue;
			
			//this loop ensures you don't have two crystite deposits in the same place
			for(int i=0;i<crystiteR.size();i++){
				if(r==crystiteR.get(i) && c==crystiteC.get(i))
					continue randomizing;
			}
			break;
		}while(true);
		
		// set the lows
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				if(r + i - j==2&&c + i + j-2==4)continue;
				try {
					lands[r + i - j][c + i + j-2].raiseCrystiteTo(1);	
					System.out.println("land["+ (r + i - j)+"]["+ (c + i + j-2)+"] set to low.");
				} catch (ArrayIndexOutOfBoundsException e) {
				}
			}
		}
		// set the mediums
		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < 2; j++) {
				if(r + i - j==2&&c + i + j-1==4)continue;
				try {
					lands[r + i - j][c + i + j-1].raiseCrystiteTo(2);
					System.out.println("land["+ (r + i - j)+"]["+ (c + i + j-1)+"] set to medium.");
				} catch (ArrayIndexOutOfBoundsException e) {
				}
			}
		}
		// set the high
		if(r!=2||c!=4)
			lands[r][c].raiseCrystiteTo(3);
		System.out.println("land["+r+"]["+c+"] set to high");
		crystiteC.add(c);
		crystiteR.add(r);
	}

	//0 = Town
	//1 = Mountain1
	//2 = Mountain2
	//3 = Mountain3
	//4 = Plains
	//5 = River
	/**
	 * private method that holds the map structure
	 * (the layout of the lands and their types)
	 * @param num the map number
	 * @return
	 */
	private String mapPattern(int num){
		if (num == 1) {
			return 	"441454344" +	//row 1
					"414454443" + 	//row 2
					"344404441" + 	//row 3
					"424454244" + 	//row 4
					"442454442"; 	//row 5
		}
		else {
			return randomize();
		}
		
	}
	
	
	
	private String randomize() {
		Random randy = new Random();
		String randomMap = "";
		for (int j = 0; j < 5; j++) {
			for (int i = 0; i < 4; i ++) {
				randomMap += (randy.nextInt(4) + 1);
			}
			if (j == 2) {
				randomMap += 0;
			} else {
				randomMap += 5;
			}
			for (int i = 0; i < 4; i ++) {
				randomMap += (randy.nextInt(4) + 1);
			}
		}
		
		return randomMap;
	}
	
	
	/**
	 * 
	 * @return the 2d array of lands the board contains
	 */
	public Land[][] getLandsArray() {
		return lands;
	}

	/**								
	 * creates a list of free lands
	 * @return list of free lands
	 */
	public ArrayList<Land> getFreeLands(){
		ArrayList<Land> freeLands= new ArrayList<Land>();
		for(int r=0;r<5;r++)
			for(int c=0;c<9;c++)
				if(lands[r][c].getOwner()==null)
					freeLands.add(lands[r][c]);
		return freeLands;
	}
	
	/**
	 * find function
	 * @param land land to be searched for
	 * @return index in lands where it's located, -1 if it doesn't
	 * 			exist in lands. The index is calculated as 9*row + col
	 */
	public int findLandIndex(Land land){
		for(int r=0;r<5;r++)
			for(int c=0;c<9;c++) {
				if(!(r == 2 && c == 4) && land == lands[r][c])
				return r*9+c;
			}
			return -1;
	}
	
	/**
	 * Sets the freeLand
	 */
	public void setNextFreeLand(Land freeLand){
		nextFreeLand = freeLand;
	}
	
	/**
	 * gets the free land
	 * @return free land
	 */
	public Land getNextFreeLand(){
		return nextFreeLand;
	}
}
